package data

// a base type.
type SlicerBase struct {
	capacity  int
	Data      []interface{}
	cmpMethod func(interface{}, interface{}) int
}

// Initializes the structure.
// the param cmpmethod is the compare method.
// This should be called by a constructor of a derived type.
func (this *SlicerBase) Init(length, capacity int, cmpmethod func(interface{}, interface{}) int) {
	if capacity < length {
		if length > 0 {
			capacity = length
		} else {
			length = 0
			capacity = 20
		}
	}
	this.capacity = capacity
	this.Data = make([]interface{}, length, capacity)
	this.cmpMethod = cmpmethod
}

// Len returns the length of the data.
func (this *SlicerBase) Len() int {
	return len(this.Data)
}

// Append appends an item to the slice.
func (this *SlicerBase) Append(item interface{}) {
	this.Data = append(this.Data, item)
}

// AtIndex returns the item at index.
func (this *SlicerBase) AtIndex(index int) interface{} {
	if index >= 0 && index < len(this.Data) {
		return this.Data[index]
	}
	return nil
}

// Index returns the first index of the item or -1.
func (this *SlicerBase) Index(item interface{}) int {
	var i, length int
	length = len(this.Data)
	for i = 0; i < length; i++ {
		if this.cmpMethod(item, this.Data[i]) == 0 {
			return i
		}
	}
	return -1
}

// LastIndex returns the last index of the item or -1.
func (this *SlicerBase) LastIndex(item interface{}) int {
	var i, length int
	length = len(this.Data)
	for i = length - 1; i >= 0; i-- {
		if this.cmpMethod(item, this.Data[i]) == 0 {
			break
		}
	}
	return i
}

// Contains returns true if item is in the slice.
func (this *SlicerBase) Contains(item interface{}) bool {
	var i int
	i = this.Index(item)
	return i >= 0
}

// DeleteAll truncates the size to 0.
func (this *SlicerBase) DeleteAll() {
	this.Data = this.Data[:0]
}

// Delete deletes the element in the slice at index.
// Param index is the slice's index of the element to be deleted.
func (this *SlicerBase) Delete(index int) {
	var length int
	length = len(this.Data)
	if index >= 0 && index < length {
		if index < length-1 {
			copy(this.Data[index:], this.Data[index+1:])
		}
		this.Data = this.Data[:length-1]
	}
}

// Remove gets an item at index
// Deletes the item at index from the array
// Returns the item
func (this *SlicerBase) Remove(index int) interface{} {
	var v interface{}
	v = this.AtIndex(index)
	this.Delete(index)
	return v
}

// Truncate truncates the size to size.
func (this *SlicerBase) Truncate(size int) {
	if size >= 0 && size < len(this.Data) {
		this.Data = this.Data[:size]
	}
}

// Reverse reverses the slice.
func (this *SlicerBase) Reverse() {
	var i, j int
	var temp interface{}
	j = len(this.Data) - 1
	for i = 0; i < j; i++ {
		temp = this.Data[i]
		this.Data[i] = this.Data[j]
		this.Data[j] = temp
		j--
	}
}
